package org.itzixi.controller;


import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.itzixi.RedisKeyConstant;
import org.itzixi.excptions.GraceException;
import org.itzixi.grace.result.GraceJSONResult;
import org.itzixi.grace.result.ResponseStatusEnum;
import org.itzixi.pojo.netty.NettyServerNode;
import org.itzixi.service.ChatMessageService;
import org.itzixi.utils.PagedGridResult;
import org.itzixi.utils.RedisOperator;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/chat")
@Slf4j
public class ChatController {

    @Resource
    private RedisOperator redis;

    @Resource
    private ChatMessageService chatMessageService;

    @Resource(name = "curatorClient")
    private CuratorFramework zkClient;


    @PostMapping("/getMyUnReadCounts")
    public GraceJSONResult getMyUnReadCounts(String myId)  {
        String key = String.join(StrUtil.COLON, RedisKeyConstant.CHAT_MSG_LIST, myId);
        Map<Object, Object> hgetall = redis.hgetall(key);
        return GraceJSONResult.ok(hgetall);
    }


    @PostMapping("/clearMyUnReadCounts")
    public GraceJSONResult clearMyUnReadCounts(String myId, String oppositeId)  {
        String key = String.join(StrUtil.COLON, RedisKeyConstant.CHAT_MSG_LIST, myId);
        redis.setHashValue(key, oppositeId, "0");
        return GraceJSONResult.ok();
    }

    @PostMapping("/list/{senderId}/{receiverId}")
    public GraceJSONResult list(@PathVariable("senderId") String senderId, @PathVariable("receiverId") String receiverId,
                                Integer page, Integer pageSize)  {
        if (StrUtil.isBlank(senderId) || StrUtil.isBlank(receiverId)){
            GraceException.display(ResponseStatusEnum.SYSTEM_ERROR_NOT_BLANK);
        }
        if (page == null || page == 0)
            page = 1;
        if (pageSize == null || pageSize == 0)
            page = 20;
        PagedGridResult pagedGridResult = chatMessageService.queryChatMsgList(senderId, receiverId, page, pageSize);
        return GraceJSONResult.ok(pagedGridResult);
    }

    @PostMapping("/signRead/{msgId}")
    public GraceJSONResult signRead(@PathVariable("msgId") String msgId)  {
        if (StrUtil.isBlank(msgId)){
            GraceException.display(ResponseStatusEnum.SYSTEM_ERROR_NOT_BLANK);
        }
        chatMessageService.updateMsgSignRead(msgId);
        return GraceJSONResult.ok();
    }

    @PostMapping("/getNettyOnlineInfo")
    public GraceJSONResult getNettyOnlineInfo()  {
        final String parentPath = "/server-list";
        try {
            // cong ZK中拿到所有的的子节点
            List<String> nodeList = zkClient.getChildren().forPath(parentPath);
            log.info("server-list下的子节点长度为：{}, 子节点都是：{}", nodeList.size(), JSONUtil.toJsonStr(nodeList));
            NettyServerNode minNettyServerNode = new NettyServerNode();
            if (!CollectionUtils.isEmpty(nodeList)){

                minNettyServerNode = nodeList.stream().map(node -> {
                    byte[] bytes = new byte[0];
                    try {
                        bytes = zkClient.getData().forPath(parentPath + StrUtil.SLASH + node);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    String nodeJson = StrUtil.str(bytes, StandardCharsets.UTF_8);
                    log.info("nodeJson：{}", nodeJson);
                    return JSONUtil.toBean(nodeJson, NettyServerNode.class);
                }).min(Comparator.comparing(NettyServerNode::getOnlineCounts)).get();
            }
            return GraceJSONResult.ok(minNettyServerNode);
        } catch (Exception e) {
            log.error("获取子节点失败：{}, {}", e, e.getMessage());
            throw new RuntimeException(e);
        }

    }


}

